package com.dylan.历史.多线程.并发编程的艺术.编程基础;

import com.dylan.历史.util.LogUtil;
import com.dylan.历史.util.SleepUtils;

/**
 * Created by Dylan on 2018/9/18.
 */
public class 线程状态 {

    private static final Object lock = new Object();

    /**
     * 模拟线程状态
     */
    public static void main(String[] args) {
        Worker worker = new Worker();
        Thread thread = new Thread(worker, "worker");
        LogUtil.info("worker线程状态：" + thread.getState()); // NEW

        thread.start();
        SleepUtils.seconds(1);
        LogUtil.info("worker线程状态：" + thread.getState()); // RUNNABLE

        worker.sleepAndExit(); // 让线程退出计算并sleep一会
        SleepUtils.seconds(1);
        LogUtil.info("worker线程状态：" + thread.getState()); // TIMED_WAITING

        doSomethingWithLock();
        SleepUtils.seconds(1);
        LogUtil.info("worker线程状态：" + thread.getState()); // BLOCKED

        SleepUtils.seconds(1);
        LogUtil.info("worker线程状态：" + thread.getState()); // WAITING

        SleepUtils.seconds(1);
        LogUtil.info("worker线程状态：" + thread.getState()); // TERMINATED
    }

    private static class Worker implements Runnable {

        private volatile boolean sleepAndExit = false;

        @Override
        public void run() {
            while (!sleepAndExit) {

            }
            SleepUtils.milliseconds(1500);

            synchronized (lock) {
                LogUtil.info(Thread.currentThread().getName() + " 上锁");
                // 启动一个线程，并等待该线程执行完
                Thread sleep = new Thread(() -> SleepUtils.seconds(1), "sleep");
                sleep.start();
                try {
                    sleep.join();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                LogUtil.info(Thread.currentThread().getName() + " 解锁");
            }
        }

        void sleepAndExit() {
            sleepAndExit = true;
        }
    }

    private static void doSomethingWithLock() {
        new Thread(() -> {
            synchronized (lock) {
                LogUtil.info(Thread.currentThread().getName() + " 上锁");
                SleepUtils.milliseconds(1500);
                LogUtil.info(Thread.currentThread().getName() + " 解锁");
            }
        },"do-some").start();
    }
}
